<script setup lang="ts">
import { onMounted, onUnmounted, ref, shallowRef, watch } from 'vue'
import { init as initEChart, type ECharts, type EChartsOption } from 'echarts'
import { LengthUnit, lengthUnitName, LengthUnitSelect, fromMeterConverter, notify } from '@/widgets'
import { ISA, AtmosphereModel, AirData } from './core'

type AirDataAttr = 'pressure' | 'temperature' | 'density' | 'soundSpeed'
const airDataAttrName: Record<AirDataAttr, string> = {
  pressure: '气压(hPa)',
  density: '密度(kg/m3)',
  soundSpeed: '音速(m/s)',
  temperature: '温度(k)'
}

function getAirDataAttrName(type: AirDataAttr) {
  return airDataAttrName[type]
}

function getAirDataAttr(type: AirDataAttr): (ad: AirData) => number {
  return (ad) => ad[type]
}

const deltaP = ref('0')
const deltaT = ref('0')
const altUnit = shallowRef<LengthUnit>(LengthUnit.M)
const airDataAttr = ref<AirDataAttr>('pressure')

let aModel: AtmosphereModel = ISA
function updateAModel(): boolean {
  const dp = parseFloat(deltaP.value)
  const dt = parseFloat(deltaT.value)
  if (isNaN(dp) || isNaN(dt)) {
    notify.error({
      title: '大气模型数值错误',
      content: '请输入正确的大气模型数值'
    })
    return false
  }
  if (dp === aModel.deltaP && dt === aModel.deltaT) {
    return false
  }
  aModel = new AtmosphereModel(dt, dp)
  return true
}

let airDataList: AirData[] = []
function updateAirDataList() {
  const size = 50
  const at = new Array<AirData>(size)
  for (let i = 0; i < size; i++) {
    at[i] = aModel.getAirData(i * 300)
  }
  airDataList = at
}

const chartEl = ref<HTMLDivElement>()
let chart: ECharts | null = null

function updateChart() {
  if (!chart) {
    return
  }
  chart.setOption(makeEChartOption())
}

function makeEChartOption(): EChartsOption {
  const chartXType = airDataAttr.value
  const xFn = getAirDataAttr(chartXType)
  const yFn = fromMeterConverter(altUnit.value)
  return {
    xAxis: {
      name: getAirDataAttrName(chartXType),
      type: 'value',
      min: 'dataMin'
    },
    yAxis: {
      name: `高度(${lengthUnitName(altUnit.value)})`,
      type: 'value'
    },
    tooltip: {
      axisPointer: { type: 'cross' }
    },
    series: [
      {
        type: 'line',
        name: 'name',
        showSymbol: false,
        data: airDataList.map((e) => [xFn(e), yFn(e.altitude)])
      }
    ]
  }
}

function updateAll() {
  if (!updateAModel()) {
    return
  }
  updateAirDataList()
  updateChart()
}

onMounted(() => {
  chart = initEChart(chartEl.value)
  updateAirDataList()
  updateChart()
})
onUnmounted(() => {
  chart?.dispose()
})

watch(altUnit, () => updateChart())
watch(airDataAttr, () => updateChart())
</script>
<template>
  <div class="air-data-calc pane-block">
    <div class="row">
      <div class="txt-box col-4em">ΔP[hPa]</div>
      <input type="number" class="input col-6em" v-model="deltaP" />
      <div class="txt-box col-3em" style="margin-left: 2em">ΔT[K]</div>
      <input type="number" class="input col-6em" v-model="deltaT" />
      <button class="button is-primary" style="margin-left: 1em" @click="updateAll">计算</button>
      <div style="margin-left: 1.5em; width: 1.5em" class="border-left" />
      <div class="col-5em txt-box">高度单位</div>
      <LengthUnitSelect v-model="altUnit" />
      <div class="col-3em txt-box" style="margin-left: 2em">属性</div>
      <div class="select col-6em">
        <select v-model="airDataAttr">
          <option value="pressure">气压</option>
          <option value="density">密度</option>
          <option value="temperature">温度</option>
          <option value="soundSpeed">音速</option>
        </select>
      </div>
    </div>
    <hr class="border-bottom" style="margin: 0.5em 0" />
    <div class="air-chart" ref="chartEl"></div>
  </div>
</template>
<style lang="scss">
.air-data-calc {
  width: 60em;
  .air-chart {
    height: 30em;
  }
}
</style>
